perm filename HELP.SAI[PNT,HE] blob sn#598725 filedate 1981-07-07 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00008 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY
C00003 00003	INTEGER #RECS,#LINKS,QUESTION_NODE,MENU_NODE,DISPLAY_NODE,PREVIOUS_DISPLAY_NODE
C00005 00004	PROCEDURE HELP_INIT
C00009 00005	PROCEDURE HELP_EXEC(INTEGER ARRAY INDEX,DATA STRING ARRAY KEYWORDS
C00019 00006	INTERNAL PROCEDURE HELP_END
C00020 00007	INTERNAL PROCEDURE HELP(STRING KEY(NULL))
C00021 00008	END
C00022 ENDMK
C⊗;
ENTRY;
BEGIN

DEFINE $$HELP=TRUE;
REQUIRE "HEADER.SAI" SOURCE_FILE;

COMMENT
	This version makes use of the file HELP.RAN and accesses the
error messages randomly.  It gives better performance than the previous
version that retrieved messages sequentially from HELP.DAT.
	;
INTEGER #RECS,#LINKS,QUESTION_NODE,MENU_NODE,DISPLAY_NODE,PREVIOUS_DISPLAY_NODE;
INTEGER CURRENT_NODE;
INTEGER ARRAY NODE_STACK[1:10];
INTEGER STACKTOP;	COMMENT CURRENT_NODE=NODE_STACK[STACKTOP];
INTEGER CHAN,BRCHAR,COUNT,EOF,FLAG,NCHAR;
STRING FNUM,FKEY,FRAN;
	! break tables;
INTEGER CR_BREAK,PP_BREAK,BB_BREAK,IGNORECR_BREAK;


DEFINE $HEAD "<>"=<"******************** H E L P   M O D E   ********************************">;
DEFINE $TAIL "<>"=<"*************************************************************************">;

RCLASS IREC (INTEGER ARRAY I);
RCLASS SREC (STRING ARRAY S);
RPTR(IREC) $INDEX,$DATA,$RANACCS;
RPTR(SREC) $KEYWORDS;

STRING $HSTRING,$KSTRING,$BSTRING;	! help string,keyword stack;
INTEGER $LINE;				! top line being displayed;

BOOLEAN HELP_INITTED;
PROCEDURE HELP_INIT;
BEGIN "help_init" ! sets up the appropriate data arrays;

FNUM←"HELP.NUM[PNT,HE]";
FKEY←"HELP.KEY[PNT,HE]";
FRAN←"HELP.RAN[PNT,HE]";

OPEN(CHAN←GETCHAN,"DSK",'10,19,0,1000,BRCHAR,EOF);
LOOKUP(CHAN,FNUM,FLAG);
#RECS←WORDIN(CHAN);
#LINKS←WORDIN(CHAN);
QUESTION_NODE←WORDIN(CHAN);
MENU_NODE←WORDIN(CHAN);

	BEGIN "read in and execute"
		! data arrays ;
	STRING ARRAY KEYWORDS[1:#RECS];
	INTEGER ARRAY INDEX[1:#RECS];
	INTEGER ARRAY DATA[1:#LINKS];
	INTEGER ARRAY RANACCS[1:#RECS];


	INTEGER I;
		! load up the arrays;
	ARRYIN(CHAN,INDEX[1],#RECS);
	ARRYIN(CHAN,DATA[1],#LINKS);
	ARRYIN(CHAN,RANACCS[1],#RECS);
	RELEASE(CHAN);

	! now get the keywords;
	OPEN(CHAN←GETCHAN,"DSK",0,19,0,1000,BRCHAR,EOF);
	LOOKUP(CHAN,FKEY,FLAG);
	! initialize the break tables;
	SETBREAK(PP_BREAK←GETBREAK,"%",NULL,"INS");
	SETBREAK(CR_BREAK←GETBREAK,LF,CR,"INS");
	SETBREAK(BB_BREAK←GETBREAK,"\",NULL,"INS");
	SETBREAK(IGNORECR_BREAK←GETBREAK,NULL,LF,"INS");
	INPUT(CHAN,PP_BREAK);	! get to beginning of data;
	INPUT(CHAN,CR_BREAK);	! prime it first;
	FOR I←1 STEP 1 UNTIL #RECS DO KEYWORDS[I]←INPUT(CHAN,CR_BREAK);
				! get the keywords;

	RELEASE(CHAN);
				! prepare input file for HELP MESSAGES ;
	OPEN(CHAN←GETCHAN,"DSK",0,19,0,NCHAR,BRCHAR,EOF);
	LOOKUP(CHAN,FRAN,FLAG);

	! put the data into records so as not to lose them ;
	$INDEX←NEW_RECORD(IREC);
		MEMORY[LOCATION(IREC:I[$INDEX])]↔MEMORY[LOCATION(INDEX)];
	$RANACCS←NEW_RECORD(IREC);
		MEMORY[LOCATION(IREC:I[$RANACCS])]↔MEMORY[LOCATION(RANACCS)];
	$DATA←NEW_RECORD(IREC);
		MEMORY[LOCATION(IREC:I[$DATA])]↔MEMORY[LOCATION(DATA)];
	$KEYWORDS←NEW_RECORD(SREC);
		MEMORY[LOCATION(SREC:S[$KEYWORDS])]↔MEMORY[LOCATION(KEYWORDS)];
	END "read in and execute";
	
HELP_INITTED←TRUE;
DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE;
STACKTOP←0;
END "help_init";
PROCEDURE HELP_EXEC(INTEGER ARRAY INDEX,DATA; STRING ARRAY KEYWORDS;
			INTEGER ARRAY RANACCS);
BEGIN "help_exec"
	! procedure returning the appropriate help message;
STRING PROCEDURE MESSAGES(INTEGER KEY);
BEGIN	INTEGER MESSAGE_LENGTH,MESSAGE_START,MESSAGE_RECORD; STRING S;
	MESSAGE_RECORD←(RANACCS[KEY] DIV 640)+1;
	MESSAGE_START←RANACCS[KEY] MOD 640;
	MESSAGE_LENGTH←RANACCS[KEY+1]-RANACCS[KEY];

	USETI(CHAN,MESSAGE_RECORD);
	NCHAR←MESSAGE_START;	S←INPUT(CHAN,0); ! gets us to beginning of mess ;
	NCHAR←MESSAGE_LENGTH;	S←INPUT(CHAN,0);	! gets us the message ;
	RETURN(S);
END;

STRING PROCEDURE NORMALIZE(STRING S);
BEGIN	! chops up long lines into lines with less 70-80 chars;
	STRING S1,S2; INTEGER C;
	IF LENGTH(S)≤80 THEN RETURN(S)
	ELSE
	S1←S[1 TO 70]; S2←S[71 TO ∞];
	DO BEGIN
		WHILE (C←LOP(S2))≠" " DO S1←S1&C;
		S1←S1&CRLF&"        "&S2[1 TO 60];
		S2←S2[61 TO ∞];
	   END UNTIL EQU(S2,NULL);
	RETURN(S1);
END;

SIMPLE INTEGER PROCEDURE ANCESTOR;
	IF STACKTOP=1 THEN RETURN(CURRENT_NODE) ELSE
		RETURN(NODE_STACK[STACKTOP-1]);

PROCEDURE DISPLAY(INTEGER NODE);
	    BEGIN "printing"
	    STRING HSTRING,KSTACK,BSTRING;INTEGER BR;INTEGER TPTR,LL,UL;
	    LL←INDEX[NODE]+1;UL←INDEX[NODE+1];
	    HSTRING←NULL;
	    FOR TPTR←LL STEP 1 UNTIL UL
		DO HSTRING←HSTRING&CVTAB(KEYWORDS[DATA[TPTR]]
			&TAB)&MESSAGES(DATA[TPTR])&CRLF;
	    KSTACK←"ANCESTORS:";
	    FOR TPTR←STACKTOP STEP -1 UNTIL 1 DO
		KSTACK←KSTACK&TAB&KEYWORDS[NODE_STACK[TPTR]];
	    $KSTRING←CVTAB(KSTACK&CRLF);
	    $KSTRING←NORMALIZE($KSTRING);
	    $HSTRING←HSTRING&CRLF;
	    IF CURRENT_NODE≠QUESTION_NODE THEN
	    BEGIN
	    BSTRING←"BRETHREN:";
	    TPTR←ANCESTOR;
	    LL←INDEX[TPTR]+1;UL←INDEX[TPTR+1];
	    FOR TPTR←LL STEP 1 UNTIL UL DO
		BSTRING←BSTRING&" "&KEYWORDS[DATA[TPTR]];
	    END ELSE BSTRING←NULL;
	    $BSTRING←CVTAB(BSTRING&CRLF);
	    $BSTRING←NORMALIZE($BSTRING);
	    SCROLL($HEAD,$HSTRING,$KSTRING&$BSTRING&$TAIL,"#### ");
	    PREVIOUS_DISPLAY_NODE←NODE;
	    END "printing";

INTEGER PROCEDURE CHECK_SUCCESSORS(STRING KEY; INTEGER NODE);
	BEGIN
	INTEGER I;
	FOR I←INDEX[NODE]+1 STEP 1 UNTIL INDEX[NODE+1] DO
		IF EQU(KEY,KEYWORDS[DATA[I]]) THEN RETURN(DATA[I]);
	RETURN(0);
	END;

INTEGER PROCEDURE CHECK_ANCESTORS(STRING KEY);
	BEGIN
	INTEGER I;
	FOR I←STACKTOP STEP -1 UNTIL 1 DO
		IF EQU(KEY,KEYWORDS[NODE_STACK[I]]) THEN RETURN(NODE_STACK[I]);
	RETURN(0);
	END;

PROCEDURE STACK(INTEGER NODE);
	BEGIN
	INTEGER I;
	FOR I←STACKTOP STEP -1 UNTIL 1 DO
		IF NODE=NODE_STACK[I] THEN BEGIN STACKTOP←I; RETURN END;
	NODE_STACK[STACKTOP←STACKTOP+1]←NODE;
	END;

PROCEDURE HELPER;
BEGIN	STRING KEY; INTEGER BROTHER_NODE,ANCESTOR_NODE,SUCCESSOR_NODE;
	DO BEGIN
	STACK(CURRENT_NODE);
	IF PREVIOUS_DISPLAY_NODE≠DISPLAY_NODE THEN DISPLAY (DISPLAY_NODE)
		ELSE OUTSTR("#### ");
	KEY←INCHWL;
	IF EQU(KEY,"?") THEN DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE
	    ELSE IF EQU(KEY,"MENU") THEN DISPLAY_NODE←CURRENT_NODE←MENU_NODE
	    ELSE IF EQU(KEY,"UP") THEN
			DISPLAY_NODE←CURRENT_NODE←ANCESTOR
	    ELSE IF EQU(KEY,NULL) OR EQU(KEY,"DONE") THEN
			DISPLAY_NODE←CURRENT_NODE
	    ELSE IF EQU(KEY,KEYWORDS[CURRENT_NODE]) THEN
			DISPLAY_NODE←CURRENT_NODE
	    ELSE IF (SUCCESSOR_NODE←CHECK_SUCCESSORS(KEY,CURRENT_NODE)) THEN
			DISPLAY_NODE←CURRENT_NODE←SUCCESSOR_NODE
	    ELSE IF (BROTHER_NODE←CHECK_SUCCESSORS(KEY,ANCESTOR))
			THEN BEGIN DISPLAY_NODE←CURRENT_NODE←BROTHER_NODE;
				STACKTOP←STACKTOP-1 END
	    ELSE IF (ANCESTOR_NODE←CHECK_ANCESTORS(KEY))
			THEN DISPLAY_NODE←CURRENT_NODE←ANCESTOR_NODE
	    ELSE DISPLAY_NODE←QUESTION_NODE;
	END UNTIL EQU(KEY,"DONE");
END;
PREVIOUS_DISPLAY_NODE←0;	! assume nothing displayed ;
HELPER;
END "help_exec";
INTERNAL PROCEDURE HELP_END;
IF HELP_INITTED THEN
BEGIN			! release the break tables;
INTEGER I;
FOR I←IGNORECR_BREAK,PP_BREAK,CR_BREAK,BB_BREAK DO RELBREAK(I);
RELEASE(CHAN);		! release the data file channel;
$INDEX←NULL_RECORD; $DATA←NULL_RECORD; $KEYWORDS←NULL_RECORD;$RANACCS←NULL_RECORD;
HELP_INITTED←FALSE;
END;
INTERNAL PROCEDURE HELP(STRING KEY(NULL));
BEGIN
	IF NOT HELP_INITTED THEN HELP_INIT;
	IF NOT EQU(KEY,NULL) THEN
	BEGIN INTEGER I;
		FOR I←#RECS STEP -1 UNTIL 1 DO IF EQU(KEY,SREC:S[$KEYWORDS][I])
			THEN DONE;
		IF I=0 THEN BEGIN PRINT("KEYWORD "&KEY&" IS UNKNOWN"&CRLF);
			    DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE;
			    END
		ELSE BEGIN DISPLAY_NODE←CURRENT_NODE←I; STACKTOP←0; END;
	END;
	HELP_EXEC(IREC:I[$INDEX],IREC:I[$DATA],SREC:S[$KEYWORDS],
		IREC:I[$RANACCS]);
	$SCROLLED←FALSE;
END;
END;